﻿using MCPlatform.Communicate.SerialPorts;
using MCPlatform.Shared.Enums;
using MCPlatform.Test.ParsingStrategy;
using System.Collections;
using System.Collections.Generic;
using System.Threading;

namespace MCPlatform.Test.Communicate
{
    public class TestBoardCommunicate
    {
        #region Fields

        private readonly string _slaveAddress = "0x81";

        private readonly string _functionCode = "0x69";


        private readonly string _subCodeLow = "0x00";

        private readonly string _subCodeHi = "0x00";


        private readonly string _dataLengthLowByte = "0x00";

        private readonly string _dataLengthHighByte = "0x00";

        //private string _CRCLow = "0x00";

        //private string _CRCHigh = "0x00";

        #endregion

        #region Properties

        public ISerialPort SerialPort { get; set; }

        public int SerialPortID { get; set; } = 1;

        #endregion

        #region CTOR

        private readonly Dictionary<ParsingOption, IParsingStrategy> strategies;


        public TestBoardCommunicate(ISerialPort serialPort)
        {
            SerialPort = serialPort;
            strategies = new Dictionary<ParsingOption, IParsingStrategy>
            {
                { ParsingOption.StationAddress, new StationAddressParsingStrategy() },
                { ParsingOption.FunctionCode, new FunctionCodeParsingStrategy() },
                { ParsingOption.SubcodeLow, new SubcodeLowParsingStrategy() },
                { ParsingOption.SubcodeHigh, new SubcodeHighParsingStrategy() },
                { ParsingOption.DataLengthLow, new DataLengthLowParsingStrategy() },
                { ParsingOption.DataLengthHigh, new DataLengthHighParsingStrategy() },
                { ParsingOption.CRCLow, new CRCLowParsingStrategy() },
                { ParsingOption.CRCHigh, new CRCHighParsingStrategy() },
                { ParsingOption.ProbeStatusHigh, new ProbeStatusHighParsingStrategy() },
                { ParsingOption.ProbeStatusLow, new ProbeStatusLowParsingStrategy() },
                { ParsingOption.ProbeConfig, new ProbeConfigParsingStrategy() },
                { ParsingOption.SamplingData, new SamplingDataParsingStrategy() },
                { ParsingOption.Ack, new AckParsingStrategy() },
                { ParsingOption.RegisterValue, new RegisterValveParsingStrategy() },
                { ParsingOption.ProbeTemperatureAndAdc, new ProbeTemperatureAndAdcParsingStrategy() },

             };


        }
        #endregion


        #region Methods 阵列

        public async Task<bool[]?> Test(int productId)
        {

            ProductTypeEnum productType = (ProductTypeEnum)productId;

            List<string> sendString = new List<string>();

            if (productType == ProductTypeEnum.阵列)
            {
                List<string> strings = new List<string> { "81", "69", "05", "00", "00", "00", "42", "CF" };
                sendString = strings;
            }
            else if (productType == ProductTypeEnum.数字探头)
            {
                List<string> strings = new List<string> { "81", "69", "01", "00", "05", "00", "10", "20", "00", "04", "64", "E9", "F3" };
                sendString = strings;
            }

          
            var response = await SerialPort.SendAndReceiveAsync(TimeSpan.FromSeconds(10), sendString: sendString.ToArray());

            var res = response?.Replace(" ", "");

            if (res == null) { return null; };

            return GetProbeStatus(res);



        }

        /// <summary>
        /// ping测试板卡指令
        /// </summary>
        /// <returns></returns>
        public async Task<bool> PingCommandAsync()
        {
            
            //原始发送的指令
            string[] rawDatas = AssamblySendStrings();

            //获取校验码并把它们组成一个字符串数组
            var sendDatas = CRC16Modbus.GetAllStrings(rawDatas);

            //16进制发送
            var response = await SerialPort.SendDataByHexAndGetReply(10000, sendString: sendDatas);

            // 去除可能存在的空格
            response = response.Replace(" ", "");

            // 选取最后4个字符组成新的字符串,就是CRC校验码
            //  string checkcode = response.Substring(response.Length - 4);

            // 去除最后4个字符，也就是祛除校验码
            // string dataString = response.Substring(0, response.Length - 4);

            //string crcCode = CRC16Modbus.ComputeChecksumToAString(dataString);

            ////计算校验码是否正确
            //if (!crcCode.Equals(checkcode))
            //{
            //    return false;
            //}
            var ack = ParseModbusString(response, ParsingOption.Ack);
            if (ack is null)
            {
                return false;
            }

            //找出最后6个字符的第一和第二个是否是A5
            if (ack.Equals("A5"))
            {
                return true;
            }

            return false;
        }



        /// <summary>
        /// 初始化板卡并获取探头配置
        /// </summary>
        /// <param name="regBytes">配置参数</param>
        /// <returns>11个探头的状态数组，11个探头的配置表</returns>
        public async Task<(bool[]?, Dictionary<ushort, byte[]>?)> InitialAndGetProbeStatusAsync(byte[] regBytes)
        {

            // 将每个字节转换为十六进制字符串，然后组合成一个字符串
            // string regString = BitConverter.ToString(regBytes).Replace("-", " ");

            string[] regString = CRC16Modbus.ByteArrayToStringArray(regBytes);

            //原始发送的指令
            List<string> rawDatas = new List<string>();


            rawDatas.AddRange(AssamblySendStrings(subCodeLow: "0x01", dataLengthLowByte: "0x0B"));

            rawDatas.AddRange(regString);

            //获取校验码并把它们组成一个字符串数组
            var sendDatas = CRC16Modbus.GetAllStrings(rawDatas.ToArray());

            //16进制发送
            var response = await SerialPort.SendDataByHexAndGetReply(10000, sendString: sendDatas);


            var dataLengthHi = ParseModbusString(response, ParsingOption.DataLengthHigh);
            if (dataLengthHi is null )
            {
                return (null, null);
            }

            //获取配置信息
            var configs = ParseModbusString(response, ParsingOption.ProbeConfig);

            //获取配置信息字典
            var probeConfigsDic = StringToByteDic(configs, 1536, 12, 128);


            return (GetProbeStatus(response), probeConfigsDic);
        }

        /// <summary>
        /// 开始采样
        /// </summary>
        /// <returns></returns>
        public async Task<bool> StartSamplingAsync()
        {
            //原始发送的指令

            string[] rawDatas = AssamblySendStrings(subCodeLow: "0x02");

            //获取校验码并把它们组成一个字符串数组
            var sendDatas = CRC16Modbus.GetAllStrings(rawDatas);

            //16进制发送
            var response = await SerialPort.SendDataByHexAndGetReply(5000, sendString: sendDatas);

            // 去除可能存在的空格
            response = response.Replace(" ", "");

            // 选取最后4个字符组成新的字符串,就是CRC校验码
            string checkcode = response.Substring(response.Length - 4);

            // 去除最后4个字符，也就是祛除校验码
            string dataString = response.Substring(0, response.Length - 4);

            //计算校验码是否正确
            //if (!CRC16Modbus.ComputeChecksumString(dataString).Equals(checkcode))
            //{
            //    return false;
            //}

            var ack = ParseModbusString(response, ParsingOption.Ack);
            if (ack is null)
            {
                return false;
            }


            //找出最后6个字符的第一和第二个是否是A5
            if (ack.Equals("A5"))
            {
                return true;
            }

            return false;
        }



        /// <summary>
        /// 停止采样并获取采样数据
        /// </summary>
        /// <returns>12个探头的状态数组，以及12个探头的采样数据，每个探头数据518byte</returns>
        public async Task<(bool[]?, Dictionary<ushort, byte[]>?)> StopSamplingAndGetSamplingDataAsync()
        {

            //停止发送指令

            string[] rawDatas = AssamblySendStrings(subCodeLow: "0x03");

            //获取校验码并把它们组成一个字符串数组
            var sendDatas = CRC16Modbus.GetAllStrings(rawDatas);

            //16进制发送
            var response = await SerialPort.SendDataByHexAndGetReply(5000, sendString: sendDatas);


            var probeStatus = GetProbeStatus(response);
            if (probeStatus == null)
            {
                return (null, null);
            }
            //获取采样信息
            var samlingData = ParseModbusString(response, ParsingOption.SamplingData);

            //获取采样信息字典
            var SamplingDataDic = StringToByteDic(samlingData, 6216, 12, 518);


            return (probeStatus, SamplingDataDic);
        }


        /// <summary>
        /// 获取探头EEPROM配置信息
        /// </summary>
        /// <returns></returns>
        public async Task<(bool[]?, Dictionary<ushort, byte[]>?)> GetProbeEEPROMConfigAsync()
        {

            //原始发送的指令

            string[] rawDatas = AssamblySendStrings(subCodeLow: "0x04");

            //获取校验码并把它们组成一个字符串数组
            var sendDatas = CRC16Modbus.GetAllStrings(rawDatas);

            //16进制发送
            var response = await SerialPort.SendDataByHexAndGetReply(5000, sendString: sendDatas);

            //获取配置信息
            var configs = ParseModbusString(response, ParsingOption.ProbeConfig);

            //获取配置信息字典
            var probeConfigsDic = StringToByteDic(configs, 1536, 12, 128);


            return (GetProbeStatus(response), probeConfigsDic);
        }

        /// <summary>
        /// 设置探头EEPROM配置信息
        /// </summary>
        /// <param name="configs">配置信息byte数组,每个128byte</param>
        /// <returns>探头连接状态数组</returns>
        public async Task<bool[]?> SetProbeEEPROMConfigAsync(byte[] configs)
        {
            if (configs == null || configs.Length < 1536)
            {
                return null;
            }

            // 将byte数组转换为字符串数组形式
            string[] stringArray = ByteArrayToHexStringArray(configs);
            //原始发送的指令        
            List<string> rawDatas = AssamblySendStrings(subCodeLow: "0x05", dataLengthLowByte: "0x06").ToList();

            //把配置信息添加进去
            rawDatas.AddRange(stringArray);


            return await SendDatasAndGetProbeStatus(rawDatas.ToArray());
        }

        /// <summary>
        /// 写入所有探头的修正数据
        /// </summary>
        /// <param name="Coefficients">12个系数的byte数组，每个3072个byte</param>
        /// <returns>探头连接状态</returns>
        public async Task<bool[]?> SetAllProbesPixelCorrectionCoefficientAsync(byte[] coefficients)
        {
            if (coefficients == null || coefficients.Length < 36888)
            {
                return null;
            }



            // 将byte数组转换为字符串数组形式
            string[] stringArray = ByteArrayToHexStringArray(coefficients);
            //原始发送的指令


            List<string> rawDatas = AssamblySendStrings(subCodeLow: "0x06", dataLengthLowByte: "0x18", dataLengthHighByte: "0x90").ToList();

            //把配置信息添加进去
            rawDatas.AddRange(stringArray);


            return await SendDatasAndGetProbeStatus(rawDatas.ToArray());
        }


        /// <summary>
        ///  写入所有探头的系数和坏点信息
        /// </summary>
        /// <param name="eeproms"> 所有探头的系数和坏点信息，每个208byte</param>
        /// <returns>探头连接状态</returns>
        public async Task<bool[]?> SetAllProbesCoefficientAndBadPointInfoAsync(byte[] eeproms)
        {
            if (eeproms == null || eeproms.Length < 2496)
            {
                return null;
            }

            // 将byte数组转换为字符串数组形式
            string[] stringArray = ByteArrayToHexStringArray(eeproms);
            //原始发送的指令

            List<string> rawDatas = AssamblySendStrings(subCodeLow: "0x08", dataLengthLowByte: "0xC6", dataLengthHighByte: "0x09").ToList();

            //把配置信息添加进去
            rawDatas.AddRange(stringArray);


            return await SendDatasAndGetProbeStatus(rawDatas.ToArray());


        }

        /// <summary>
        /// 结束板卡工作
        /// </summary>
        /// <returns></returns>

        public async Task<bool[]?> EndWorkAsync()
        {
            //原始发送的指令

            string[] rowDatas = AssamblySendStrings(subCodeLow: "0x07");

            return await SendDatasAndGetProbeStatus(rowDatas);

        }

        /// <summary>
        /// 发送数据并获取探头状态
        /// </summary>
        /// <param name="datas">发送数据</param>
        /// <returns>探头状态</returns>
        public async Task<bool[]?> SendDatasAndGetProbeStatus(string[] datas)
        {
            //获取校验码并把它们组成一个字符串数组
            var sendDatas = CRC16Modbus.GetAllStrings(datas);

            //16进制发送
            var response = await SerialPort.SendDataByHexAndGetReply(20000, sendString: sendDatas);


            return (GetProbeStatus(response));
        }

        /// <summary>
        /// 集成发送字符串
        /// </summary>
        /// <param name="subCodeLow">子功能码低位</param>
        /// <param name="subCodeHi">子功能码高位</param>
        /// <param name="dataLengthLowByte">数据长度低位</param>
        /// <param name="dataLengthHighByte">数据长度高位</param>
        /// <param name="dataStrings">数据字符串</param>
        /// <returns></returns>
        public string[] AssamblySendStrings(string? subCodeLow = null, string? subCodeHi = null, string? dataLengthLowByte = null, string? dataLengthHighByte = null, string? dataStrings = null)
        {
            subCodeLow = subCodeLow ?? _subCodeLow;
            subCodeHi = subCodeHi ?? _subCodeHi;
            dataLengthLowByte = dataLengthLowByte ?? _dataLengthLowByte;
            dataLengthHighByte = dataLengthHighByte ?? _dataLengthHighByte;
            //原始发送的指令
            List<string> rowDatas = new List<string> { _slaveAddress, _functionCode, subCodeLow, subCodeHi, dataLengthLowByte, dataLengthHighByte };

            if (dataStrings != null)
            {
                rowDatas.Add(dataStrings);
            }


            return rowDatas.ToArray();
        }






        #endregion



        #region Methods 数字探头

        /// <summary>
        /// 初始化探头并配置TO1-TA模式
        /// </summary>
        /// <param name="level">档位，默认：16</param>
        /// <param name="gain">增益，默认：64</param>
        /// <param name="samplingRate">采样率，默认：16384</param>
        /// <param name="radiationCoefficient">辐射系数，默认：100</param>
        /// <param name="timeSpen">超时时间：默认10s,单位ms</param>
        /// <returns>探头状态</returns>

        public async Task<bool[]?> InitialProbesAndConfigsTO1_TAAsync(int level = 16, int gain = 64, int samplingRate = 16384, int radiationCoefficient = 1, double timeSpen = 10000)
        {

            string levelHex = level.ToString("X2");

            string gainHex = gain.ToString("X2");

            string[] samplingRateHex = IntToHexString(samplingRate);

            string radiationCoefficientHex = radiationCoefficient.ToString("X2");

            //原始发送的指令
            List<string> rawDatas = new List<string>();


            rawDatas.AddRange(AssamblySendStrings(subCodeLow: "0x01", dataLengthLowByte: "0x05"));

            //挡位
            rawDatas.Add(levelHex);

            //增益
            rawDatas.Add(gainHex);

            //采样率
            rawDatas.AddRange(samplingRateHex);

            //辐射系数
            rawDatas.Add(radiationCoefficientHex);

            //获取校验码并把它们组成一个字符串数组
            var sendDatas = CRC16Modbus.GetAllStrings(rawDatas.ToArray());

            //16进制发送
            var response = await SerialPort.SendDataByHexAndGetReply(timeSpen, sendString: sendDatas);


            var dataLengthHi = ParseModbusString(response, ParsingOption.DataLengthHigh);
            if (response is null || dataLengthHi is null)
            {
                return (null);
            }

            //返回配置信息
            return (GetProbeStatus(response));
        }


        /// <summary>
        /// 保存EE-BLOW数据
        /// </summary>
        /// <param name="timeSpen">超时时间</param>
        /// <returns></returns>
        public async Task<bool[]?> SaveEEBlowDataAsync(double timeSpen = 10000)
        {



            //原始发送的指令
            List<string> rawDatas = new List<string>();

            //保存数据ee-blow
            rawDatas.AddRange(AssamblySendStrings(subCodeLow: "0x02"));
           

            //获取校验码并把它们组成一个字符串数组
            var sendDatas = CRC16Modbus.GetAllStrings(rawDatas.ToArray());

            //16进制发送
            var response = await SerialPort.SendDataByHexAndGetReply(timeSpen, sendString: sendDatas);


            var dataLengthHi = ParseModbusString(response, ParsingOption.DataLengthHigh);
            if (dataLengthHi is null)
            {
                return (null);
            }

            //返回配置信息
            return (GetProbeStatus(response));
        }


        /// <summary>
        /// 读取环境温度和目标温度
        /// </summary>
        /// <param name="timeSpen">超时时间</param>
        /// <returns></returns>
        public async Task<(bool[]?, Dictionary<ushort, byte[]>?)> ReadAmbientTempeAndTargetTempeAsync(double timeSpen = 10000)
        {

            //原始发送的指令
            List<string> rawDatas = new List<string>();

            //保存数据ee-blow
            rawDatas.AddRange(AssamblySendStrings(subCodeLow: "0x03"));


            //获取校验码并把它们组成一个字符串数组
            var sendDatas = CRC16Modbus.GetAllStrings(rawDatas.ToArray());

            //16进制发送
            var response = await SerialPort.SendDataByHexAndGetReply(timeSpen, sendString: sendDatas);

            var probeTempAndAdc = ParseModbusString(response, ParsingOption.ProbeTemperatureAndAdc);

            //获取配置信息字典
            var probeTempAndAdcDic = StringToByteDic(probeTempAndAdc, 192, 12, 16);


            var dataLengthHi = ParseModbusString(response, ParsingOption.DataLengthHigh);
            if (dataLengthHi is null)
            {
                return (null, probeTempAndAdcDic);
            }

            



            //返回配置信息
            return (GetProbeStatus(response), probeTempAndAdcDic);
        }

        /// <summary>
        /// 校准环境温度
        /// </summary>
        /// <param name="temperature">环境温度</param>
        /// <param name="samplingTimes">采样次数</param>
        /// <param name="timeSpen">超时时间</param>
        /// <returns>探头状态</returns>
        public async Task<bool[]?> CalibrateAmbientTempeAsync(int temperature,int samplingTimes,double timeSpen = 10000)
        {
            string[] tempe= IntToHexString(temperature);

            string[] samplingTime = IntToHexString(samplingTimes);

            //原始发送的指令
            List<string> rawDatas = new List<string>();

            //校准环境温度
            rawDatas.AddRange(AssamblySendStrings(subCodeLow: "0x04",dataLengthLowByte:"0x01"));

            //环境温度
            rawDatas.AddRange(tempe);  

            //采样次数
            rawDatas.AddRange(samplingTime);

            //获取校验码并把它们组成一个字符串数组
            var sendDatas = CRC16Modbus.GetAllStrings(rawDatas.ToArray());

            //16进制发送
            var response = await SerialPort.SendDataByHexAndGetReply(timeSpen, sendString: sendDatas);


            var dataLengthHi = ParseModbusString(response, ParsingOption.DataLengthHigh);
            if (dataLengthHi is null )
            {
                return (null);
            }

            //返回配置信息
            return (GetProbeStatus(response));
        }


        /// <summary>
        /// 写入VT表
        /// </summary>
        /// <param name="minTempe">最低温度</param>
        /// <param name="maxTempe">最高温度</param>
        /// <param name="vtTable">VT表</param>
        /// <param name="timeSpen">超时时间</param>
        /// <returns>探头状态</returns>
        public async Task<bool[]?> WriteVtTable(int minTempe, int maxTempe, string[] vtTable, double timeSpen = 10000)
        {
           

            string[] minTempeHex = IntToHexString(minTempe);

            string[] maxTempeHex = IntToHexString(maxTempe);

            //原始发送的指令
            List<string> rawDatas = new List<string>();

            //校准环境温度
            rawDatas.AddRange(AssamblySendStrings(subCodeLow: "0x08", dataLengthLowByte: "0x04",dataLengthHighByte:"0x03"));

          
            //最低温度
            rawDatas.AddRange(minTempeHex);


            //最高温度
            rawDatas.AddRange(maxTempeHex);


            //vtTable
           // string[] vtTableHex = CRC16Modbus.ByteArrayToStringArray(vtTable);

            rawDatas.AddRange(vtTable);


            //获取校验码并把它们组成一个字符串数组
            var sendDatas = CRC16Modbus.GetAllStrings(rawDatas.ToArray());

            //16进制发送
            var response = await SerialPort.SendDataByHexAndGetReply(timeSpen, sendString: sendDatas);


            var dataLengthHi = ParseModbusString(response, ParsingOption.DataLengthHigh);
            if (dataLengthHi is null )
            {
                return (null);
            }

            //返回配置信息
            return (GetProbeStatus(response));
        }


        /// <summary>
        /// 校准offset
        /// </summary>
        /// <param name="offset">偏移值</param>
        /// <param name="samplingTimes">采样次数</param>
        /// <param name="timeSpen">超时时间</param>
        /// <returns>探头状态</returns>
        public async Task<bool[]?> CalibrateOffsetAsync(float offset, int samplingTimes, double timeSpen = 10000)
        {
            string[] offsetHex = FloatToHexString(offset);

            string[] samplingTime = IntToHexString(samplingTimes);

            //原始发送的指令
            List<string> rawDatas = new List<string>();

            //校准环境温度
            rawDatas.AddRange(AssamblySendStrings(subCodeLow: "0x05", dataLengthLowByte: "0x05"));

            //校准值
            rawDatas.AddRange(offsetHex);

            //采样次数
            rawDatas.AddRange(samplingTime);

            //获取校验码并把它们组成一个字符串数组
            var sendDatas = CRC16Modbus.GetAllStrings(rawDatas.ToArray());

            //16进制发送
            var response = await SerialPort.SendDataByHexAndGetReply(timeSpen, sendString: sendDatas);


            var dataLengthHi = ParseModbusString(response, ParsingOption.DataLengthHigh);
            if (dataLengthHi is null )
            {
                return (null);
            }

            //返回配置信息
            return (GetProbeStatus(response));
        }

        /// <summary>
        /// 校准增益
        /// </summary>
        /// <param name="gain">增益值</param>
        /// <param name="samplingTimes">采样次数</param>
        /// <param name="timeSpen">超时时间</param>
        /// <returns>探头状态</returns>
        public async Task<bool[]?> CalibrateGainAsync(float gain, int samplingTimes, double timeSpen = 10000)
        {
            string[] gainHex = FloatToHexString(gain);

            string[] samplingTime = IntToHexString(samplingTimes);

            //原始发送的指令
            List<string> rawDatas = new List<string>();

            //组合指令
            rawDatas.AddRange(AssamblySendStrings(subCodeLow: "0x06", dataLengthLowByte: "0x05"));

            //增益值
            rawDatas.AddRange(gainHex);

            //采样次数
            rawDatas.AddRange(samplingTime);

            //获取校验码并把它们组成一个字符串数组
            var sendDatas = CRC16Modbus.GetAllStrings(rawDatas.ToArray());

            //16进制发送
            var response = await SerialPort.SendDataByHexAndGetReply(timeSpen, sendString: sendDatas);


            var dataLengthHi = ParseModbusString(response, ParsingOption.DataLengthHigh);
            if (dataLengthHi is null)
            {
                return (null);
            }

            //返回配置信息
            return (GetProbeStatus(response));
        }


        /// <summary>
        /// 暂停采集环境温度和目标温度
        /// </summary>
        /// <param name="timeSpen">超时时间</param>
        /// <returns>探头状态</returns>
        public async Task<bool[]?> PauseSamplingAmbientTempeAndTargetTempeAsync(double timeSpen = 10000)
        {
           
            //原始发送的指令
            List<string> rawDatas = new List<string>();

            //组合指令
            rawDatas.AddRange(AssamblySendStrings(subCodeLow: "0x07"));

          

            //获取校验码并把它们组成一个字符串数组
            var sendDatas = CRC16Modbus.GetAllStrings(rawDatas.ToArray());

            //16进制发送
            var response = await SerialPort.SendDataByHexAndGetReply(timeSpen, sendString: sendDatas);


            var dataLengthHi = ParseModbusString(response, ParsingOption.DataLengthHigh);
            if (dataLengthHi is null || dataLengthHi.Equals("00"))
            {
                return (null);
            }

            //返回配置信息
            return (GetProbeStatus(response));
        }


        /// <summary>
        /// 清除环境温度校准系数
        /// </summary>
        /// <param name="timeSpen">超时时间</param>
        /// <returns></returns>
        public async Task<bool[]?> ClearAmbientTempeCalibraCoefficientAsync(double timeSpen = 10000)
        {

            //原始发送的指令
            List<string> rawDatas = new List<string>();

            //组合指令
            rawDatas.AddRange(AssamblySendStrings(subCodeLow: "0x09"));



            //获取校验码并把它们组成一个字符串数组
            var sendDatas = CRC16Modbus.GetAllStrings(rawDatas.ToArray());

            //16进制发送
            var response = await SerialPort.SendDataByHexAndGetReply(timeSpen, sendString: sendDatas);


            var dataLengthHi = ParseModbusString(response, ParsingOption.DataLengthHigh);
            if (dataLengthHi is null )
            {
                return (null);
            }

            //返回配置信息
            return (GetProbeStatus(response));
        }

        /// <summary>
        /// 清除offset校准系数
        /// </summary>
        /// <param name="timeSpen">超时时间</param>
        /// <returns>探头状态</returns>
        public async Task<bool[]?> ClearOffsetCalibraCoefficientAsync(double timeSpen = 10000)
        {

            //原始发送的指令
            List<string> rawDatas = new List<string>();

            //组合指令
            rawDatas.AddRange(AssamblySendStrings(subCodeLow: "0x0a"));


            //获取校验码并把它们组成一个字符串数组
            var sendDatas = CRC16Modbus.GetAllStrings(rawDatas.ToArray());

            //16进制发送
            var response = await SerialPort.SendDataByHexAndGetReply(timeSpen, sendString: sendDatas);


            var dataLengthHi = ParseModbusString(response, ParsingOption.DataLengthHigh);
            if (dataLengthHi is null)
            {
                return (null);
            }

            //返回配置信息
            return (GetProbeStatus(response));
        }


        /// <summary>
        /// 清除增益校准系数
        /// </summary>
        /// <param name="timeSpen">超时时间</param>
        /// <returns></returns>
        public async Task<bool[]?> ClearGainCalibraCoefficientAsync(double timeSpen = 10000)
        {

            //原始发送的指令
            List<string> rawDatas = new List<string>();

            //组合指令
            rawDatas.AddRange(AssamblySendStrings(subCodeLow: "0x0b"));


            //获取校验码并把它们组成一个字符串数组
            var sendDatas = CRC16Modbus.GetAllStrings(rawDatas.ToArray());

            //16进制发送
            var response = await SerialPort.SendDataByHexAndGetReply(timeSpen, sendString: sendDatas);


            var dataLengthHi = ParseModbusString(response, ParsingOption.DataLengthHigh);
            if (dataLengthHi is null)
            {
                return (null);
            }

            //返回配置信息
            return (GetProbeStatus(response));
        }


        /// <summary>
        /// 写任意寄存器地址
        /// </summary>
        /// <param name="registerAddr">寄存器地址</param>
        /// <param name="value">值</param>
        /// <param name="timeSpen">超时时间</param>
        /// <returns>探头状态</returns>
        public async Task<bool[]?> WriteRegisterAsync(string registerAddr,string value,double timeSpen = 10000)
        {
           // string registerAddrHex = registerAddr.ToString("X");

           // string valueHex = value.ToString("X");
            //原始发送的指令
            List<string> rawDatas = new List<string>();

            //组合指令
            rawDatas.AddRange(AssamblySendStrings(subCodeLow: "0x0c",dataLengthLowByte:"0x02"));


            //寄存器地址
            rawDatas.Add(registerAddr);

            //寄存器值
            rawDatas.Add(value);

            //获取校验码并把它们组成一个字符串数组
            var sendDatas = CRC16Modbus.GetAllStrings(rawDatas.ToArray());

            //16进制发送
            var response = await SerialPort.SendDataByHexAndGetReply(timeSpen, sendString: sendDatas);


            var dataLengthHi = ParseModbusString(response, ParsingOption.DataLengthHigh);
            if (dataLengthHi is null)
            {
                return (null);
            }

            //返回配置信息
            return (GetProbeStatus(response));
        }


        /// <summary>
        /// 读取任意寄存器值
        /// </summary>
        /// <param name="registerAddr">寄存器地址</param>
        /// <param name="timeSpen">超时时间</param>
        /// <returns>探头状态，探头寄存器值</returns>
        public async Task<(bool[]?, Dictionary<ushort, byte[]>?)> ReadRegisterAsync(string registerAddr, double timeSpen = 10000)
        {
           // string registerAddrHex = registerAddr.ToString("X");
         
            //原始发送的指令
            List<string> rawDatas = new List<string>();

            //组合指令
            rawDatas.AddRange(AssamblySendStrings(subCodeLow: "0x0d", dataLengthLowByte: "0x01"));


            //寄存器地址
            rawDatas.Add(registerAddr);

           

            //获取校验码并把它们组成一个字符串数组
            var sendDatas = CRC16Modbus.GetAllStrings(rawDatas.ToArray());

            //16进制发送
            var response = await SerialPort.SendDataByHexAndGetReply(timeSpen, sendString: sendDatas);


            var dataLengthHi = ParseModbusString(response, ParsingOption.DataLengthHigh);
            if (dataLengthHi is null)
            {
                return (null,null);
            }


            var registerValue = ParseModbusString(response,ParsingOption.RegisterValue);

            //获取寄存器地址值
            var registerDic = StringToByteDic(registerValue, 12, 12, 1);
            //返回配置信息,寄存器地址值
            return (GetProbeStatus(response), registerDic);
        }




        #endregion


        #region auxiliary function 

        /// <summary>
        /// 获取探头状态数组
        /// </summary>
        /// <param name="input">输入板卡返回字符串</param>
        /// <returns>bool型数组</returns>
        public bool[]? GetProbeStatus(string input)
        {
            string? probeLow = ParseModbusString(input, ParsingOption.ProbeStatusLow);

            string? probeHi = ParseModbusString(input, ParsingOption.ProbeStatusHigh);

            //    if (probeLow is null || probeHi is null || (probeLow.Equals("00") && probeHi.Equals("00")))
            if (probeLow is null || probeHi is null)
             {
                return null;
            }

            probeHi = probeHi + probeLow;

            var probeBytes = StringToByteArray(probeHi);

            return ByteArrayToBoolArray(probeBytes);
        }

       


        /// <summary>
        /// 根据输入字符串，解析回字节数组，以字典方式返回
        /// </summary>
        /// <param name="inputString">串口返回的字符串</param>
        /// <param name="length">字节长度</param>
        /// <param name="count">分成字典的key数量</param>
        /// <param name="chunkSize">字典每个key的value大小，即字节数组的长度</param>
        /// <returns></returns>
        public Dictionary<ushort, byte[]>? StringToByteDic(string? inputString, int length, ushort count, int chunkSize)
        {
            //转成byte数组
            var probeConfigs = StringToByteArray(inputString);
            if (probeConfigs is null || probeConfigs.Length < length)
            {
                return null;
            }

            return SplitArray(probeConfigs, count, chunkSize);
        }




        /// <summary>
        /// 解析板卡返回字符串的值
        /// </summary>
        /// <param name="input">输入板卡返回字符串</param>
        /// <param name="option">选择要返回的数据类型</param>
        /// <returns></returns>
        public string? ParseModbusString(string input, ParsingOption option)
        {
            if (input.Length < 11)
            {
                return null;
            }
            string data = input.Replace(" ","");
            if (strategies.TryGetValue(option, out var strategy))
            {
                return strategy.Parse(data);
            }

            return null;
        }

        /// <summary>
        /// 把byte数组拆分成多个byte数组
        /// </summary>
        /// <param name="originalArray">源数组</param>
        /// <param name="count">拆分数量</param>
        /// <param name="chunkSize">拆分长度</param>
        /// <returns></returns>
        static Dictionary<ushort, byte[]> SplitArray(byte[] originalArray, ushort count = 12, int chunkSize = 128)
        {
            Dictionary<ushort, byte[]> dictionary = new Dictionary<ushort, byte[]>();

            for (ushort i = 0; i < count; i++)
            {
                byte[] chunk = new byte[chunkSize];
                Array.Copy(originalArray, i * chunkSize, chunk, 0, chunkSize);
                dictionary.Add(i, chunk);
            }

            return dictionary;
        }

        /// <summary>
        /// 16进制字符串转byte数组
        /// </summary>
        /// <param name="hex"></param>
        /// <returns></returns>
        static byte[]? StringToByteArray(string? hex)
        {
            if (hex is null)
            {
                return null;
            }
            int numberChars = hex.Length;
            byte[] bytes = new byte[numberChars / 2];
            for (int i = 0; i < numberChars; i += 2)
            {
                bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
            }
            return bytes;
        }

        /// <summary>
        /// byte数组转bool数组
        /// </summary>
        /// <param name="byteArray"></param>
        /// <returns></returns>
        static bool[]? ByteArrayToBoolArray(byte[]? byteArray)
        {
            if (byteArray is null)
            {
                return null;
            }
            bool[] boolArray = new bool[byteArray.Length * 8];
            for (int i = 0; i < byteArray.Length; i++)
            {
                for (int j = 0; j < 8; j++)
                {
                    boolArray[i * 8 + j] = (byteArray[i] & (1 << (7 - j))) != 0;
                }
            }

            Array.Reverse(boolArray);

            return boolArray;
        }


        // 将byte数组转换为字符串数组形式（不包含连字符）
        static string[] ByteArrayToHexStringArray(byte[] byteArray)
        {
            string[] stringArray = new string[byteArray.Length];
            for (int i = 0; i < byteArray.Length; i++)
            {
                stringArray[i] = byteArray[i].ToString("X2");
            }
            return stringArray;
        }


        static string[] FloatToHexString(float value)
        {
            byte[] bytes = BitConverter.GetBytes(value);
            if (!BitConverter.IsLittleEndian)
            {
                Array.Reverse(bytes);
            }

            string hexString = BitConverter.ToString(bytes).Replace("-", "");
            if (hexString.Length > 2)
            {
                if (hexString.Length % 2 > 0)
                {
                    hexString = "0" + hexString;
                }

                List<string> splitStrings = new List<string>();


                // 循环每次取两个字符，并将它们添加到列表中
                for (int i = 0; i < hexString.Length; i += 2)
                {
                    // 取两个字符，如果不足两个则只取一个
                    string substring = hexString.Substring(i, Math.Min(2, hexString.Length - i));
                    splitStrings.Add(substring);
                }

            


                return splitStrings.ToArray();
            }
            return new string[] { hexString }; ;
        }

     

        static string[] UintToHexString(uint value)
        {
            //byte[] bytes = BitConverter.GetBytes((ushort)value);
            //if (!BitConverter.IsLittleEndian)
            //{
            //    Array.Reverse(bytes);
            //}

            string hexString = Convert.ToString(value, 16);
            if (hexString.Length > 2)
            {
                if (hexString.Length % 2 > 0)
                {
                    hexString = "0" + hexString;
                }
                List<string> splitStrings = new List<string>();


                // 循环每次取两个字符，并将它们添加到列表中
                for (int i = 0; i < hexString.Length; i += 2)
                {
                    // 取两个字符，如果不足两个则只取一个
                    string substring = hexString.Substring(i, Math.Min(2, hexString.Length - i));
                    splitStrings.Add(substring);
                }

                return splitStrings.ToArray();
         
            }

            return  new string[] { hexString} ;
        }   


        public static string[] IntToHexString(int value)
        {
           

            // 将正整数转换为16进制字符串
            string hexString = Convert.ToString(value, 16);

            // 如果16进制字符串长度超过4位，则截取最后4位
            if (hexString.Length > 4)
            {
                hexString = hexString.Substring(hexString.Length - 4);
            }
           

            if (hexString.Length > 2)
            {
                if (hexString.Length % 2 > 0)
                {
                   hexString = "0" + hexString;
                }
                string[] splitStrings = new string[2];
                splitStrings[0] = hexString.Substring(0, 2); // 取前两个字符
                splitStrings[1] = hexString.Substring(2); // 取剩余的字符

               
                return splitStrings;
            }

          
            if (hexString.Length < 2)
            {
                hexString =  "0" + hexString;
            }

            return new string[] { hexString };
        }

        public static string[] IntToHexStringAtLeast2Byte(int value)
        {

            var hex = IntToHexString(value);
            if (hex.Length == 1)
            {
                return new string[] { "00", hex[0] };
            }
            
            return hex;


        }


        #endregion



    }
}
